package com.fengyi.library.service.impl;

import com.fengyi.library.model.Book;
import com.fengyi.library.model.Loan;
import com.fengyi.library.model.User;
import com.fengyi.library.repository.LoanRepository;
import com.fengyi.library.service.BookService;
import com.fengyi.library.service.LoanService;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;

@Service
public class LoanServiceImpl implements LoanService {

    private final LoanRepository loanRepository;
    private final BookService bookService;

    @Autowired
    public LoanServiceImpl(LoanRepository loanRepository, BookService bookService) {
        this.loanRepository = loanRepository;
        this.bookService = bookService;
    }

    @Override
    public Loan findById(Integer id) {
        return loanRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("借阅记录不存在，ID: " + id));
    }

    @Override
    public Page<Loan> findLoansByUser(User user, Pageable pageable) {
        return loanRepository.findByUser(user, pageable);
    }

    @Override
    public List<Loan> findCurrentLoansByUser(User user) {
        return loanRepository.findByUserAndStatus(user, Loan.LoanStatus.BORROWED);
    }
    
    @Override
    public List<Loan> findReturnedLoansByUser(User user) {
        return loanRepository.findByUserAndStatus(user, Loan.LoanStatus.RETURNED);
    }
    
    @Override
    public List<Loan> findOverdueLoansByUser(User user) {
        LocalDate today = LocalDate.now();
        return loanRepository.findByUserAndStatus(user, Loan.LoanStatus.BORROWED)
                .stream()
                .filter(loan -> loan.getDueDate().isBefore(today))
                .toList();
    }

    @Override
    public List<Loan> findLoansByBook(Book book) {
        return loanRepository.findByBookAndStatus(book, Loan.LoanStatus.BORROWED);
    }

    @Override
    public List<Loan> findOverdueLoans() {
        return loanRepository.findOverdueLoans(LocalDate.now());
    }

    @Override
    @Transactional
    public Loan borrowBook(User user, Book book, int loanDays) {
        // 检查图书是否可借
        if (!bookService.isBookAvailable(book.getId())) {
            throw new RuntimeException("图书当前不可借阅");
        }

        // 检查用户是否已借阅此书
        if (hasUserBorrowedBook(user, book)) {
            throw new RuntimeException("您已借阅此书，不能重复借阅");
        }

        // 默认借阅期限为30天，如果指定了天数则使用指定的天数
        int days = loanDays > 0 ? loanDays : 30;

        // 创建借阅记录
        Loan loan = new Loan();
        loan.setUser(user);
        loan.setBook(book);
        loan.setBorrowDate(LocalDate.now());
        loan.setDueDate(LocalDate.now().plusDays(days));
        loan.setStatus(Loan.LoanStatus.BORROWED);

        // 更新图书可用数量
        bookService.updateBookQuantity(book.getId(), -1);

        return loanRepository.save(loan);
    }

    @Override
    @Transactional
    public Loan returnBook(Integer loanId) {
        Loan loan = findById(loanId);

        // 检查图书是否已归还
        if (loan.getStatus() == Loan.LoanStatus.RETURNED) {
            throw new RuntimeException("此书已归还");
        }

        // 更新借阅状态
        loan.setReturnDate(LocalDate.now());
        loan.setStatus(Loan.LoanStatus.RETURNED);

        // 更新图书可用数量
        bookService.updateBookQuantity(loan.getBook().getId(), 1);

        return loanRepository.save(loan);
    }

    @Override
    public boolean hasUserBorrowedBook(User user, Book book) {
        return loanRepository.countBorrowedBooksByUser(user, book) > 0;
    }

    @Override
    public long countCurrentBorrowedBooks(User user) {
        return loanRepository.countCurrentBorrowedBooks(user);
    }
    
    @Override
    public long countReturnedBooks(User user) {
        return findReturnedLoansByUser(user).size();
    }
    
    @Override
    public long countOverdueBooks(User user) {
        return findOverdueLoansByUser(user).size();
    }

    @Override
    public Page<Loan> findAllLoans(Pageable pageable) {
        // 先检查并更新所有借阅状态，确保数据最新
        updateLoanStatus();
        return loanRepository.findAll(pageable);
    }
    
    @Override
    @Transactional
    public void updateLoanStatus() {
        LocalDate today = LocalDate.now();
        List<Loan> overdueLoans = loanRepository.findByStatusAndDueDateBefore(
                Loan.LoanStatus.BORROWED, today);
        
        for (Loan loan : overdueLoans) {
            loan.setStatus(Loan.LoanStatus.OVERDUE);
            loanRepository.save(loan);
        }
    }
    
    @Override
    public Page<Loan> findAllOverdueLoans(Pageable pageable) {
        updateLoanStatus(); // Ensure statuses are up-to-date
        return loanRepository.findByStatus(Loan.LoanStatus.OVERDUE, pageable);
    }

    @Override
    public Page<Loan> searchLoans(String keyword, Pageable pageable) {
        // 先更新借阅状态，确保数据最新
        updateLoanStatus();
        
        // 使用仓库的searchLoans方法进行搜索
        return loanRepository.searchLoans(keyword, pageable);
    }
}
